package com.ruoyi.exam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.exam.domain.ExamRandomPractice;
import com.ruoyi.exam.domain.ExamRandomPracticeQuestion;
import com.ruoyi.exam.vo.ExamRandomPracticeVo;
import com.ruoyi.exam.vo.ExamRandomPracticeQuestionIdsVo;
import com.ruoyi.exam.vo.QuestionPracticeStatusVo;
import com.ruoyi.exam.vo.ExamErrorQuestionVo;
import com.ruoyi.exam.vo.ExamQuestionDetailVo;
import com.ruoyi.exam.vo.ExamQuestionOptionVo;
import com.ruoyi.exam.vo.SubmitAnswerVo;
import com.ruoyi.exam.vo.SubmitAnswerResultVo;
import com.ruoyi.exam.mapper.ExamRandomPracticeMapper;
import com.ruoyi.exam.service.IExamRandomPracticeService;
import com.ruoyi.exam.service.IExamRandomPracticeQuestionService;
import com.ruoyi.exam.service.IExamBankQuestionService;
import com.ruoyi.exam.service.IExamErrorQuestionService;
import com.ruoyi.exam.service.IExamQuestionService;
import com.ruoyi.exam.vo.ExamQuestionWithSortVo;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 练习Service业务层处理
 *
 * @author Tellsea
 * @date 2025-07-28
 */
@Service
public class ExamRandomPracticeServiceImpl extends ServiceImpl<ExamRandomPracticeMapper, ExamRandomPractice> implements IExamRandomPracticeService {

    @Autowired
    private IExamRandomPracticeQuestionService examRandomPracticeQuestionService;

    @Autowired
    private IExamBankQuestionService examBankQuestionService;

    @Autowired
    private IExamQuestionService examQuestionService;

    @Autowired
    private IExamErrorQuestionService examErrorQuestionService;

    public static final int PRACTICE_QUESTION_COUNT = 10;

    @Override
    public TableDataInfo<ExamRandomPracticeVo> queryList(ExamRandomPracticeVo entity) {
        return PageUtils.buildDataInfo(this.baseMapper.queryList(PageUtils.buildPage(), entity));
    }

    @Override
    public List<ExamRandomPracticeVo> queryAll(ExamRandomPracticeVo entity) {
        return this.baseMapper.queryList(entity);
    }

    @Override
    public ExamRandomPracticeVo queryById(Long practiceId) {
        return this.baseMapper.queryById(practiceId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExamRandomPracticeVo createRandomPractice(Long bankId, String questionType, Long userId) {
        // 1. 检查是否有未完成的练习
        ExamRandomPracticeVo unfinishedPractice = checkUnfinishedPractice(bankId, questionType, userId);
        if (unfinishedPractice != null) {
            throw new RuntimeException("您还有未完成的练习，请先完成当前练习");
        }

        // 2. 从题库中随机获取道题目
        List<ExamQuestionWithSortVo> allQuestions = examBankQuestionService.getQuestionsByBankId(userId, bankId);
        
        // 如果指定了题目类型，则按类型筛选
        if (questionType != null && !questionType.isEmpty()) {
            allQuestions = allQuestions.stream()
                    .filter(q -> questionType.equals(q.getQuestionType()))
                    .collect(java.util.stream.Collectors.toList());
        }
        
        if (allQuestions.size() < 10) {
            throw new RuntimeException("题库中的题目数量不足" + PRACTICE_QUESTION_COUNT + "道，无法创建练习");
        }

        // 随机选择道题目
        List<ExamQuestionWithSortVo> selectedQuestions = getRandomQuestions(allQuestions, PRACTICE_QUESTION_COUNT);

        // 3. 创建练习记录
        ExamRandomPractice practice = new ExamRandomPractice();
        practice.setUserId(userId);
        practice.setBankId(bankId);
        practice.setQuestionType(questionType);
        practice.setPracticeName("随机练习-" + DateUtils.getDate());
        practice.setQuestionCount(Long.valueOf(PRACTICE_QUESTION_COUNT));
        practice.setCompletedCount(0L);
        practice.setTotalScore(calculateTotalScore(selectedQuestions));
        practice.setCurrentScore(BigDecimal.ZERO);
        practice.setPracticeStatus("0"); // 进行中
        practice.setStartTime(new Date());
        practice.setTimeLimit(60L); // 默认60分钟
        practice.setCreateBy(SecurityUtils.getUsername());
        practice.setCreateTime(DateUtils.getNowDate());
        practice.setUpdateBy(SecurityUtils.getUsername());
        practice.setUpdateTime(DateUtils.getNowDate());

        // 保存练习记录
        this.save(practice);

        // 4. 创建练习题目关联记录
        List<ExamRandomPracticeQuestion> practiceQuestions = new ArrayList<>();
        for (int i = 0; i < selectedQuestions.size(); i++) {
            ExamQuestionWithSortVo question = selectedQuestions.get(i);
            ExamRandomPracticeQuestion practiceQuestion = new ExamRandomPracticeQuestion();
            practiceQuestion.setPracticeId(practice.getPracticeId());
            practiceQuestion.setQuestionId(question.getQuestionId());
            practiceQuestion.setQuestionOrder((long) (i + 1));
            practiceQuestion.setUserAnswer(null);
            practiceQuestion.setIsCorrect(null);
            practiceQuestion.setCreateTime(DateUtils.getNowDate());
            practiceQuestion.setUpdateTime(DateUtils.getNowDate());
            practiceQuestions.add(practiceQuestion);
        }

        // 批量保存练习题目
        examRandomPracticeQuestionService.saveBatch(practiceQuestions);

        // 5. 返回练习信息
        ExamRandomPracticeVo result = new ExamRandomPracticeVo();
        result.setPracticeId(practice.getPracticeId());
        result.setUserId(practice.getUserId());
        result.setBankId(practice.getBankId());
        result.setQuestionType(practice.getQuestionType());
        result.setPracticeName(practice.getPracticeName());
        result.setQuestionCount(practice.getQuestionCount());
        result.setCompletedCount(practice.getCompletedCount());
        result.setTotalScore(practice.getTotalScore());
        result.setCurrentScore(practice.getCurrentScore());
        result.setPracticeStatus(practice.getPracticeStatus());
        result.setStartTime(practice.getStartTime());
        result.setTimeLimit(practice.getTimeLimit());

        return result;
    }

    @Override
    public ExamRandomPracticeVo checkUnfinishedPractice(Long bankId, String questionType, Long userId) {
        LambdaQueryWrapper<ExamRandomPractice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExamRandomPractice::getUserId, userId)
                .eq(ExamRandomPractice::getBankId, bankId)
                .eq(ExamRandomPractice::getPracticeStatus, "0") // 进行中的练习
                .eq(ExamRandomPractice::getQuestionType, questionType) // 题目类型
                .orderByDesc(ExamRandomPractice::getCreateTime)
                .last("LIMIT 1");

        ExamRandomPractice unfinishedPractice = this.getOne(wrapper);
        if (unfinishedPractice != null) {
            ExamRandomPracticeVo result = new ExamRandomPracticeVo();
            result.setPracticeId(unfinishedPractice.getPracticeId());
            result.setUserId(unfinishedPractice.getUserId());
            result.setBankId(unfinishedPractice.getBankId());
            result.setQuestionType(unfinishedPractice.getQuestionType());
            result.setPracticeName(unfinishedPractice.getPracticeName());
            result.setQuestionCount(unfinishedPractice.getQuestionCount());
            result.setCompletedCount(unfinishedPractice.getCompletedCount());
            result.setTotalScore(unfinishedPractice.getTotalScore());
            result.setCurrentScore(unfinishedPractice.getCurrentScore());
            result.setPracticeStatus(unfinishedPractice.getPracticeStatus());
            result.setStartTime(unfinishedPractice.getStartTime());
            result.setTimeLimit(unfinishedPractice.getTimeLimit());
            return result;
        }
        return null;
    }

    /**
     * 从题目列表中随机选择指定数量的题目
     */
    private List<ExamQuestionWithSortVo> getRandomQuestions(List<ExamQuestionWithSortVo> allQuestions, int count) {
        List<ExamQuestionWithSortVo> shuffled = new ArrayList<>(allQuestions);
        Collections.shuffle(shuffled);
        return shuffled.subList(0, Math.min(count, shuffled.size()));
    }

    /**
     * 计算总分
     */
    private BigDecimal calculateTotalScore(List<ExamQuestionWithSortVo> questions) {
        return questions.stream()
                .map(ExamQuestionWithSortVo::getScore)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    @Override
    public ExamRandomPracticeQuestionIdsVo getQuestionIds(Long practiceId) {
        ExamRandomPracticeQuestionIdsVo result = new ExamRandomPracticeQuestionIdsVo();
        
        // 1. 查询该练习的所有题目，并按题目顺序排序
        LambdaQueryWrapper<ExamRandomPracticeQuestion> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExamRandomPracticeQuestion::getPracticeId, practiceId)
                .orderByAsc(ExamRandomPracticeQuestion::getQuestionOrder);
        List<ExamRandomPracticeQuestion> practiceQuestions = examRandomPracticeQuestionService.list(wrapper);
        
        // 2. 组装题目答题状态列表，并查找未开始答的第一题
        List<QuestionPracticeStatusVo> questionList = new ArrayList<>();
        Long firstUnansweredQuestionId = null;
        Integer firstUnansweredQuestionIndex = null;
        
        // 检查是否所有题目都未答题
        boolean hasNoAnswers = true;
        for (ExamRandomPracticeQuestion practiceQuestion : practiceQuestions) {
            String userAnswer = practiceQuestion.getUserAnswer();
            if (userAnswer != null && !userAnswer.trim().isEmpty()) {
                hasNoAnswers = false;
                break;
            }
        }
        
        if (practiceQuestions != null) {
            for (int i = 0; i < practiceQuestions.size(); i++) {
                ExamRandomPracticeQuestion practiceQuestion = practiceQuestions.get(i);
                QuestionPracticeStatusVo statusVo = new QuestionPracticeStatusVo();
                statusVo.setQuestionId(practiceQuestion.getQuestionId());
                statusVo.setSortOrder(practiceQuestion.getQuestionOrder());
                
                // 检查是否有答题记录
                String userAnswer = practiceQuestion.getUserAnswer();
                if (userAnswer != null && !userAnswer.trim().isEmpty()) {
                    statusVo.setHasAnswered(true);
                    // "1"表示正确，"0"表示错误
                    statusVo.setIsCorrect("1".equals(practiceQuestion.getIsCorrect()));
                } else {
                    statusVo.setHasAnswered(false);
                    statusVo.setIsCorrect(null);
                    
                    // 如果是第一个未答题的题目，记录其ID和索引
                    if (firstUnansweredQuestionId == null) {
                        firstUnansweredQuestionId = practiceQuestion.getQuestionId();
                        firstUnansweredQuestionIndex = i;
                    }
                }
                
                questionList.add(statusVo);
            }
            
            // 如果用户完全没有答题记录，返回第一题ID和索引
            if (hasNoAnswers && !practiceQuestions.isEmpty()) {
                firstUnansweredQuestionId = practiceQuestions.get(0).getQuestionId();
                firstUnansweredQuestionIndex = 0;
            }
        }
        
        // 构建返回对象
        result.setQuestionList(questionList);
        result.setFirstUnansweredQuestionId(firstUnansweredQuestionId);
        result.setFirstUnansweredQuestionIndex(firstUnansweredQuestionIndex);
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExamRandomPracticeVo restartPractice(Long bankId, String questionType, Long userId) {
        // 1. 查询当前用户当前题库下的该种题目的所有练习（包括已完成和进行中的）
        LambdaQueryWrapper<ExamRandomPractice> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExamRandomPractice::getUserId, userId)
                .eq(ExamRandomPractice::getBankId, bankId)
                .eq(ExamRandomPractice::getPracticeStatus, "0")
                .eq(ExamRandomPractice::getQuestionType, questionType);
        
        List<ExamRandomPractice> practices = this.list(wrapper);
        
        // 2. 如果存在练习，则删除相关的练习题目数据和练习数据
        if (!practices.isEmpty()) {
            // 2.1 获取所有练习的ID列表
            List<Long> practiceIds = practices.stream()
                    .map(ExamRandomPractice::getPracticeId)
                    .collect(Collectors.toList());
            
            // 2.2 删除这些练习关联的所有练习题目数据
            LambdaQueryWrapper<ExamRandomPracticeQuestion> questionWrapper = new LambdaQueryWrapper<>();
            questionWrapper.in(ExamRandomPracticeQuestion::getPracticeId, practiceIds);
            examRandomPracticeQuestionService.remove(questionWrapper);
            
            // 2.3 删除这些练习数据
            this.removeByIds(practiceIds);
        }
        
        // 3. 创建新的随机练习（不检查未完成练习，因为旧练习已删除）
        ExamRandomPracticeVo newPractice = createRandomPracticeWithoutCheck(
                bankId, 
                questionType, 
                userId
        );
        
        // 4. 返回新建的随机练习对象
        return newPractice;
    }

    /**
     * 创建随机练习（不检查未完成练习）
     * 用于重新练习场景
     *
     * @param bankId 题库ID
     * @param questionType 题目类型
     * @param userId 用户ID
     * @return 练习信息
     */
    private ExamRandomPracticeVo createRandomPracticeWithoutCheck(Long bankId, String questionType, Long userId) {
        // 从题库中随机获取题目
        List<ExamQuestionWithSortVo> allQuestions = examBankQuestionService.getQuestionsByBankId(userId, bankId);
        
        // 如果指定了题目类型，则按类型筛选
        if (questionType != null && !questionType.isEmpty()) {
            allQuestions = allQuestions.stream()
                    .filter(q -> questionType.equals(q.getQuestionType()))
                    .collect(java.util.stream.Collectors.toList());
        }
        
        if (allQuestions.size() < 10) {
            throw new RuntimeException("题库中的题目数量不足，无法创建练习");
        }

        // 随机选择题目
        List<ExamQuestionWithSortVo> selectedQuestions = getRandomQuestions(allQuestions, PRACTICE_QUESTION_COUNT);

        // 创建练习记录
        ExamRandomPractice practice = new ExamRandomPractice();
        practice.setUserId(userId);
        practice.setBankId(bankId);
        practice.setQuestionType(questionType);
        practice.setPracticeName("随机练习-" + DateUtils.getDate());
        practice.setQuestionCount(Long.valueOf(PRACTICE_QUESTION_COUNT));
        practice.setCompletedCount(0L);
        practice.setTotalScore(calculateTotalScore(selectedQuestions));
        practice.setCurrentScore(BigDecimal.ZERO);
        practice.setPracticeStatus("0"); // 进行中
        practice.setStartTime(new Date());
        practice.setTimeLimit(60L); // 默认60分钟
        practice.setCreateBy(SecurityUtils.getUsername());
        practice.setCreateTime(DateUtils.getNowDate());
        practice.setUpdateBy(SecurityUtils.getUsername());
        practice.setUpdateTime(DateUtils.getNowDate());

        // 保存练习记录
        this.save(practice);

        // 创建练习题目关联记录
        List<ExamRandomPracticeQuestion> practiceQuestions = new ArrayList<>();
        for (int i = 0; i < selectedQuestions.size(); i++) {
            ExamQuestionWithSortVo question = selectedQuestions.get(i);
            ExamRandomPracticeQuestion practiceQuestion = new ExamRandomPracticeQuestion();
            practiceQuestion.setPracticeId(practice.getPracticeId());
            practiceQuestion.setQuestionId(question.getQuestionId());
            practiceQuestion.setQuestionOrder((long) (i + 1));
            practiceQuestion.setUserAnswer(null);
            practiceQuestion.setIsCorrect(null);
            practiceQuestion.setCreateTime(DateUtils.getNowDate());
            practiceQuestion.setUpdateTime(DateUtils.getNowDate());
            practiceQuestions.add(practiceQuestion);
        }

        // 批量保存练习题目
        examRandomPracticeQuestionService.saveBatch(practiceQuestions);

        // 返回练习信息
        ExamRandomPracticeVo result = new ExamRandomPracticeVo();
        result.setPracticeId(practice.getPracticeId());
        result.setUserId(practice.getUserId());
        result.setBankId(practice.getBankId());
        result.setQuestionType(practice.getQuestionType());
        result.setPracticeName(practice.getPracticeName());
        result.setQuestionCount(practice.getQuestionCount());
        result.setCompletedCount(practice.getCompletedCount());
        result.setTotalScore(practice.getTotalScore());
        result.setCurrentScore(practice.getCurrentScore());
        result.setPracticeStatus(practice.getPracticeStatus());
        result.setStartTime(practice.getStartTime());
        result.setTimeLimit(practice.getTimeLimit());

        return result;
    }

    @Override
    public ExamQuestionDetailVo queryQuestionDetail(Long practiceId, Long questionId, Long userId) {
        // 1. 查询练习题目关联记录，获取该题目在练习中的答题状态
        LambdaQueryWrapper<ExamRandomPracticeQuestion> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExamRandomPracticeQuestion::getPracticeId, practiceId)
                .eq(ExamRandomPracticeQuestion::getQuestionId, questionId);
        ExamRandomPracticeQuestion practiceQuestion = examRandomPracticeQuestionService.getOne(wrapper);
        
        if (practiceQuestion == null) {
            throw new RuntimeException("该题目不属于本次练习");
        }

        // 2. 获取题目详细信息
        ExamQuestionDetailVo questionDetail = examQuestionService.queryDetailById(questionId, userId);
        if (questionDetail == null) {
            throw new RuntimeException("题目不存在");
        }

        // 3. 更新练习中的答题状态信息
        String userAnswer = practiceQuestion.getUserAnswer();
        if (userAnswer != null && !userAnswer.trim().isEmpty()) {
            questionDetail.setHasAnswered(true);
            questionDetail.setSelectedOptions(userAnswer);
            if (practiceQuestion.getIsCorrect() != null) {
                questionDetail.setIsCorrect("1".equals(practiceQuestion.getIsCorrect()));
            } else {
                questionDetail.setIsCorrect(null);
            }
        } else {
            questionDetail.setHasAnswered(false);
            questionDetail.setSelectedOptions(null);
            questionDetail.setIsCorrect(null);
        }

        return questionDetail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SubmitAnswerResultVo submitAnswer(SubmitAnswerVo submitAnswerVo, Long userId) {
        // 1. 验证练习ID和题目ID
        if (submitAnswerVo.getPracticeId() == null) {
            throw new RuntimeException("练习ID不能为空");
        }
        if (submitAnswerVo.getQuestionId() == null) {
            throw new RuntimeException("题目ID不能为空");
        }

        // 2. 验证练习是否存在且属于当前用户
        ExamRandomPractice practice = this.getById(submitAnswerVo.getPracticeId());
        if (practice == null) {
            throw new RuntimeException("练习不存在");
        }
        if (!practice.getUserId().equals(userId)) {
            throw new RuntimeException("无权访问该练习");
        }

        // 3. 验证题目是否属于该练习
        LambdaQueryWrapper<ExamRandomPracticeQuestion> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExamRandomPracticeQuestion::getPracticeId, submitAnswerVo.getPracticeId())
                .eq(ExamRandomPracticeQuestion::getQuestionId, submitAnswerVo.getQuestionId());
        ExamRandomPracticeQuestion practiceQuestion = examRandomPracticeQuestionService.getOne(wrapper);
        if (practiceQuestion == null) {
            throw new RuntimeException("该题目不属于本次练习");
        }

        // 4. 获取题目详细信息
        ExamQuestionDetailVo questionDetail = examQuestionService.queryDetailById(submitAnswerVo.getQuestionId(), userId);
        if (questionDetail == null) {
            throw new RuntimeException("题目不存在");
        }

        // 5. 判断答案是否正确并计算得分
        SubmitAnswerResultVo result = new SubmitAnswerResultVo();
        boolean isCorrect = checkAnswer(questionDetail, submitAnswerVo);
        if(!isCorrect){
            //错误，加入错题记录
            ExamErrorQuestionVo errorQuestion = new ExamErrorQuestionVo();
            errorQuestion.setUserId(userId);
            errorQuestion.setBankId(submitAnswerVo.getBankId());
            errorQuestion.setQuestionId(submitAnswerVo.getQuestionId());
            examErrorQuestionService.addErrorQuestion(errorQuestion);
        }
        result.setIsCorrect(isCorrect);
        result.setSelectedOptions(submitAnswerVo.getUserAnswer());

        // 获取正确选项
        List<String> correctOptions = questionDetail.getOptions().stream()
                .filter(option -> "1".equals(option.getIsCorrect()))
                .map(ExamQuestionOptionVo::getOptionLabel)
                .collect(Collectors.toList());
        result.setCorrectOptions(correctOptions);
        result.setQuestionAnalysis(questionDetail.getQuestionAnalysis());

        // 计算得分
        BigDecimal score = BigDecimal.ZERO;
        if (isCorrect && questionDetail.getScore() != null) {
            score = questionDetail.getScore();
        }
        result.setScore(score);

        // 6. 更新练习题目关联记录
        boolean isFirstAnswer = (practiceQuestion.getUserAnswer() == null || practiceQuestion.getUserAnswer().trim().isEmpty());
        practiceQuestion.setUserAnswer(submitAnswerVo.getUserAnswer());
        practiceQuestion.setIsCorrect(isCorrect ? "1" : "0");
        practiceQuestion.setScore(score);
        practiceQuestion.setAnswerTime(new Date());
        if (submitAnswerVo.getAnswerTime() != null) {
            practiceQuestion.setTimeSpent(submitAnswerVo.getAnswerTime());
        }
        practiceQuestion.setUpdateTime(DateUtils.getNowDate());
        examRandomPracticeQuestionService.updateById(practiceQuestion);

        // 7. 更新练习信息
        if (isFirstAnswer) {
            // 第一次答题，增加完成数和得分
            practice.setCompletedCount(practice.getCompletedCount() + 1);
            practice.setCurrentScore(practice.getCurrentScore().add(score));
        } else {
            // 重新答题，需要调整得分（减去之前的得分，加上新的得分）
            BigDecimal oldScore = practiceQuestion.getScore() != null ? practiceQuestion.getScore() : BigDecimal.ZERO;
            practice.setCurrentScore(practice.getCurrentScore().subtract(oldScore).add(score));
        }

        // 检查是否已完成所有题目
        LambdaQueryWrapper<ExamRandomPracticeQuestion> allQuestionsWrapper = new LambdaQueryWrapper<>();
        allQuestionsWrapper.eq(ExamRandomPracticeQuestion::getPracticeId, submitAnswerVo.getPracticeId());
        long totalQuestions = examRandomPracticeQuestionService.count(allQuestionsWrapper);
        
        LambdaQueryWrapper<ExamRandomPracticeQuestion> answeredWrapper = new LambdaQueryWrapper<>();
        answeredWrapper.eq(ExamRandomPracticeQuestion::getPracticeId, submitAnswerVo.getPracticeId())
                .isNotNull(ExamRandomPracticeQuestion::getUserAnswer)
                .ne(ExamRandomPracticeQuestion::getUserAnswer, "");
        long answeredQuestions = examRandomPracticeQuestionService.count(answeredWrapper);

        if (answeredQuestions >= totalQuestions) {
            // 所有题目都已完成
            practice.setPracticeStatus("1"); // 已完成
            practice.setEndTime(new Date());
        }

        practice.setUpdateTime(DateUtils.getNowDate());
        practice.setUpdateBy(SecurityUtils.getUsername());
        this.updateById(practice);

        // 8. 获取下一题信息
        SubmitAnswerResultVo.NextQuestionInfo nextQuestion = new SubmitAnswerResultVo.NextQuestionInfo();
        LambdaQueryWrapper<ExamRandomPracticeQuestion> nextWrapper = new LambdaQueryWrapper<>();
        nextWrapper.eq(ExamRandomPracticeQuestion::getPracticeId, submitAnswerVo.getPracticeId())
                .gt(ExamRandomPracticeQuestion::getQuestionOrder, practiceQuestion.getQuestionOrder())
                .orderByAsc(ExamRandomPracticeQuestion::getQuestionOrder)
                .last("LIMIT 1");
        ExamRandomPracticeQuestion nextPracticeQuestion = examRandomPracticeQuestionService.getOne(nextWrapper);
        
        if (nextPracticeQuestion != null) {
            nextQuestion.setQuestionId(nextPracticeQuestion.getQuestionId());
            nextQuestion.setSortOrder(nextPracticeQuestion.getQuestionOrder());
            nextQuestion.setHasNext(true);
        } else {
            nextQuestion.setHasNext(false);
        }
        result.setNextQuestion(nextQuestion);

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExamRandomPracticeVo completePractice(Long practiceId, Long userId) {
        // 1. 验证练习是否存在且属于当前用户
        ExamRandomPractice practice = this.getById(practiceId);
        if (practice == null) {
            throw new RuntimeException("练习不存在");
        }
        if (!practice.getUserId().equals(userId)) {
            throw new RuntimeException("无权访问该练习");
        }

        // 2. 检查练习是否已经是已完成状态
        if ("1".equals(practice.getPracticeStatus())) {
            // 已经是已完成状态，直接返回
            ExamRandomPracticeVo result = new ExamRandomPracticeVo();
            result.setPracticeId(practice.getPracticeId());
            result.setUserId(practice.getUserId());
            result.setBankId(practice.getBankId());
            result.setQuestionType(practice.getQuestionType());
            result.setPracticeName(practice.getPracticeName());
            result.setQuestionCount(practice.getQuestionCount());
            result.setCompletedCount(practice.getCompletedCount());
            result.setTotalScore(practice.getTotalScore());
            result.setCurrentScore(practice.getCurrentScore());
            result.setPracticeStatus(practice.getPracticeStatus());
            result.setStartTime(practice.getStartTime());
            result.setEndTime(practice.getEndTime());
            result.setTimeLimit(practice.getTimeLimit());
            return result;
        }

        // 3. 更新练习状态为已完成
        practice.setPracticeStatus("1"); // 已完成
        practice.setEndTime(new Date());
        practice.setUpdateBy(SecurityUtils.getUsername());
        practice.setUpdateTime(DateUtils.getNowDate());
        this.updateById(practice);

        // 4. 返回更新后的练习信息
        ExamRandomPracticeVo result = new ExamRandomPracticeVo();
        result.setPracticeId(practice.getPracticeId());
        result.setUserId(practice.getUserId());
        result.setBankId(practice.getBankId());
        result.setQuestionType(practice.getQuestionType());
        result.setPracticeName(practice.getPracticeName());
        result.setQuestionCount(practice.getQuestionCount());
        result.setCompletedCount(practice.getCompletedCount());
        result.setTotalScore(practice.getTotalScore());
        result.setCurrentScore(practice.getCurrentScore());
        result.setPracticeStatus(practice.getPracticeStatus());
        result.setStartTime(practice.getStartTime());
        result.setEndTime(practice.getEndTime());
        result.setTimeLimit(practice.getTimeLimit());

        return result;
    }

    /**
     * 检查答案是否正确
     */
    private boolean checkAnswer(ExamQuestionDetailVo questionDetail, SubmitAnswerVo submitAnswerVo) {
        String questionType = questionDetail.getQuestionType();
        
        // 获取正确选项
        List<String> correctOptions = questionDetail.getOptions().stream()
                .filter(option -> "1".equals(option.getIsCorrect()))
                .map(ExamQuestionOptionVo::getOptionLabel)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(correctOptions)) {
            return false;
        }

        // 客观题判断
        if ("1".equals(questionType) || "2".equals(questionType) || "3".equals(questionType)) {
            if (!StringUtils.hasText(submitAnswerVo.getUserAnswer())) {
                return false;
            }
            
            // 处理用户答案，支持逗号、分号等分隔符
            String userAnswer = submitAnswerVo.getUserAnswer().replaceAll("[,;，；\\s]", "");
            List<String> userOptions = Arrays.asList(userAnswer.split(""));
            userOptions = userOptions.stream()
                    .filter(opt -> !opt.isEmpty())
                    .collect(Collectors.toList());
            
            return userOptions.size() == correctOptions.size() && 
                   userOptions.containsAll(correctOptions) && 
                   correctOptions.containsAll(userOptions);
        }
        
        // 主观题暂时返回true，实际需要人工判分
        return true;
    }
}
